home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / glibc108.zip / glibc108 / mach / devstream.c < prev    next >
C/C++ Source or Header  |  1994-05-23  |  5KB  |  237 lines

  1. /* stdio on a Mach device port.
  2.    Translates \n to \r\n on output.
  3.  
  4. Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
  5. This file is part of the GNU C Library.
  6.  
  7. The GNU C Library is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU Library General Public License as
  9. published by the Free Software Foundation; either version 2 of the
  10. License, or (at your option) any later version.
  11.  
  12. The GNU C Library is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. Library General Public License for more details.
  16.  
  17. You should have received a copy of the GNU Library General Public
  18. License along with the GNU C Library; see the file COPYING.LIB.  If
  19. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  20. Cambridge, MA 02139, USA.  */
  21.  
  22. #include <stdio.h>
  23. #include <mach.h>
  24. #include <device/device.h>
  25. #include <errno.h>
  26. #include <string.h>
  27.  
  28. static int
  29. input (FILE *f)
  30. {
  31.   kern_return_t err;
  32.   char *buffer;
  33.   size_t to_read;
  34.   mach_msg_type_size_t nread;
  35.   char c;
  36.  
  37.   if (f->__buffer == NULL)
  38.     {
  39.       buffer = &c;
  40.       to_read = 1;
  41.     }
  42.   else
  43.     {
  44.       buffer = f->__buffer;
  45.       to_read = f->__bufsize;
  46.     }
  47.  
  48.   f->__eof = 0;
  49.  
  50.   nread = to_read;
  51.   if (err = device_read_inband ((device_t) f->__cookie, 0, f->__target,
  52.                 to_read, buffer, &nread))
  53.     {
  54.       f->__error = 1;
  55.       f->__bufp = f->__get_limit = f->__put_limit = f->__buffer;
  56.       errno = err;
  57.       return EOF;
  58.     }
  59.  
  60.   if (f->__buffer == NULL)
  61.     return (unsigned char) c;
  62.  
  63.   f->__get_limit = f->__buffer + nread;
  64.   f->__bufp = f->__buffer;
  65.   f->__put_limit = f->__buffer + (f->__mode.__write ? f->__bufsize : 0);
  66.   return (unsigned char) *f->__bufp++;
  67. }
  68.  
  69.  
  70. static void
  71. output (FILE *f, int c)
  72. {
  73.   inline void write_some (const char *p, size_t to_write)
  74.     {
  75.       kern_return_t err;
  76.       int wrote;
  77.       while (to_write > 0)
  78.     {
  79.       if (err = device_write ((device_t) f->__cookie, 0,
  80.                   f->__target, (char *)p, 
  81.                   to_write, &wrote))
  82.         {
  83.           errno = err;
  84.           f->__error = 1;
  85.           break;
  86.         }
  87.       p += wrote;
  88.       to_write -= wrote;
  89.       f->__target += wrote;
  90.     }
  91.     }
  92.  
  93.   if (f->__buffer != NULL)
  94.     {
  95.       if (f->__put_limit == f->__buffer)
  96.     {
  97.       /* Prime the stream for writing.  */
  98.       f->__put_limit = f->__buffer + f->__bufsize;
  99.       f->__bufp = f->__buffer;
  100.       if (c != EOF)
  101.         {
  102.           *f->__bufp++ = (unsigned char) c;
  103.           c = EOF;
  104.         }
  105.     }
  106.  
  107.  
  108.       /* Write out the buffer.  */
  109.  
  110.       write_some (f->__buffer, f->__bufp - f->__buffer);
  111.  
  112.       f->__bufp = f->__buffer;
  113.     }
  114.  
  115.   if (c != EOF && !ferror (f))
  116.     {
  117.       if (f->__linebuf && (unsigned char) c == '\n')
  118.     {
  119.       static const char nl = '\n';
  120.       write_some (&nl, 1);
  121.     }
  122.       else
  123.     *f->__bufp++ = (unsigned char) c;
  124.     }
  125. }
  126.  
  127.  
  128.  
  129. #if 0                /* Translates \n to \r\n.  */
  130. static void
  131. output (FILE *f, int c)
  132. {
  133.   void write_some (const char *p, size_t to_write)
  134.     {
  135.       kern_return_t err;
  136.       int wrote;
  137.       while (to_write > 0)
  138.     {
  139.       if (err = device_write_inband ((device_t) f->__cookie, 0,
  140.                      f->__target, p, to_write, &wrote))
  141.         {
  142.           errno = err;
  143.           f->__error = 1;
  144.           break;
  145.         }
  146.       p += wrote;
  147.       to_write -= wrote;
  148.       f->__target += wrote;
  149.     }
  150.     }
  151.   void write_crlf (void)
  152.     {
  153.       static const char crlf[] = "\r\n";
  154.       write_some (crlf, 2);
  155.     }
  156.  
  157.   if (f->__buffer == NULL)
  158.     {
  159.       /* The stream is unbuffered.  */
  160.  
  161.       if (c == '\n')
  162.     write_crlf ();
  163.       else if (c != EOF)
  164.     {
  165.       char cc = (unsigned char) c;
  166.       write_some (&cc, 1);
  167.     }
  168.  
  169.       return;
  170.     }
  171.  
  172.   if (f->__put_limit == f->__buffer)
  173.     {
  174.       /* Prime the stream for writing.  */
  175.       f->__put_limit = f->__buffer + f->__bufsize;
  176.       f->__bufp = f->__buffer;
  177.       if (c != EOF)
  178.     {
  179.       *f->__bufp++ = (unsigned char) c;
  180.       c = EOF;
  181.     }
  182.     }
  183.  
  184.   {
  185.     /* Search for newlines (LFs) in the buffer.  */
  186.  
  187.     char *start = f->__buffer, *p = start;
  188.  
  189.     while (!ferror (f) && (p = memchr (p, '\n', f->__bufp - start)))
  190.       {
  191.     /* Found one.  Replace it with a CR and write out through that CR.  */
  192.  
  193.     *p = '\r';
  194.     write_some (start, p + 1 - start);
  195.  
  196.     /* Change it back to an LF; the next iteration will write it out
  197.        first thing.  Start the next searching iteration one char later.  */
  198.  
  199.     start = p;
  200.     *p++ = '\n';
  201.       }
  202.  
  203.     /* Write the remainder of the buffer.  */
  204.  
  205.     if (!ferror (f))
  206.       write_some (start, f->__bufp - start);
  207.   }
  208.  
  209.   f->__bufp = f->__buffer;
  210.  
  211.   if (c != EOF && !ferror (f))
  212.     {
  213.       if (f->__linebuf && (unsigned char) c == '\n')
  214.     write_crlf ();
  215.       else
  216.     *f->__bufp++ = (unsigned char) c;
  217.     }
  218. }
  219. #endif
  220.  
  221. FILE *
  222. mach_open_devstream (mach_port_t dev, const char *mode)
  223. {
  224.   FILE *stream = fopencookie ((void *) dev, mode, __default_io_functions);
  225.   if (stream == NULL)
  226.     return NULL;
  227.  
  228.   stream->__room_funcs.__input = input;
  229.   stream->__room_funcs.__output = output;
  230.   stream->__io_funcs.__close = (__io_close_fn *) device_close;
  231.   stream->__io_funcs.__seek = NULL; /* Cannot seek.  */
  232.   stream->__io_funcs.__fileno = NULL; /* No corresponding POSIX.1 fd.  */
  233.   stream->__seen = 1;
  234.  
  235.   return stream;
  236. }
  237.